package com.lagou.client;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 最快响应负载均衡策略实现  每次都选择最后一次响应时间短的服务端进行服务调用，如果时间一致，随机选取一个服务端进行调用，从而实现负载均衡
 */
@Slf4j
public class FastBalanceStrategy {
    public static RpcConsumer getConsumer() {
        // 获取当前连接列表
        List<RpcConsumer> consumers = ConnectionManager.getManager().getConsumers();
        if (!consumers.isEmpty()) {
            // 获取最后响应时间为0，或者最后更新速度时间超过5秒的连接（归0）
            // ，如果有，则为第一优先级，直接从中获取连接
            List<RpcConsumer> freeConsumers = consumers.stream()
                    .filter(c -> c.getServerInfo().getLastAckSpeed() == 0
                            || (System.currentTimeMillis() - c.getServerInfo().getLastAckTime()) > 5000)
                    .collect(Collectors.toList());
            if (!freeConsumers.isEmpty()) {
                // 从归0集合中随机获取一个连接
                RpcConsumer consumer = consumers.get(new Random().nextInt(consumers.size()));
                log.info("随机选择归0连接[{}]", consumer.getServerInfo().getServerName());
                return consumer;
            } else {
                // 如果归0集合为空，则对所有连接按响应时间排序，并取首位
                // 需求中如果响应时间相同则取随机，应该没有必要，如果最小的两个相同，取第一个发送后，响应时间就会重新计算
                consumers.sort((c1, c2) -> (int) (c1.getServerInfo().getLastAckSpeed() - c2.getServerInfo().getLastAckSpeed()));
                RpcConsumer consumer = consumers.get(0);

                // 打印选择过程
                log.info("选择最快连接[{}] => [{}]", consumer.getServerInfo().getServerName(), StringUtils.collectionToDelimitedString(
                        consumers.stream().map(c -> String.format("%s:%d", c.getServerInfo().getServerName(), c.getServerInfo().getLastAckSpeed()))
                                .collect(Collectors.toList()), ","
                ));
                return consumer;
            }
        }
        return null;
    }
}
